home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / clipper / regxsrch.zip / REGXSRCH.C < prev   
C/C++ Source or Header  |  1992-01-27  |  7KB  |  202 lines

  1. /*
  2.  * regxsrch.c    Tue Jan 21 1992 15:28:47
  3.  *
  4.  *
  5.  * Synopsis:
  6.  * ~~~~~~~~~
  7.  * A regular-expression searcher for Clipper.  Uses the GNU regex library
  8.  * (as contained in the GNUISH MSDOS project's GNULIB, available in the
  9.  * pd:<msdos.gnuish> directory on Simtel20 and the mirror sites) to do
  10.  * the actual regex searching; thus the Clipper program must be linked
  11.  * against the GNU library (large model version) as well as this code and
  12.  * the C library.
  13.  *
  14.  * Note that this makes no re_set_syntax() call, so the regex functions
  15.  * are left to use the regex library's compile-time default syntax code.
  16.  * As the regex library is distributed, this is 0, giving the egrep syntax
  17.  * except that `\|' is required for the OR operator (`|' by itself is just
  18.  * a literal), and `\(' and `\)' are required for grouping (`(' and `)' are
  19.  * literals).  See the file regex.h in the GNULIB or regexlib distributions
  20.  * for details of the available options.
  21.  *
  22.  *
  23.  * Warning:
  24.  * ~~~~~~~~
  25.  * I consider this release a Beta test version.  There are no known bugs,
  26.  * and I have tested it thoroughly, but I will not accept responsibility
  27.  * for anything untoward it may do.  If it sinks your house in a swamp,
  28.  * kills your dog, and phones your boss and calls him a dirty bastard,
  29.  * you will have only yourself to blame.  However, I would appreciate
  30.  * hearing of any bugs you may find, and I will probably fix them.
  31.  *
  32.  *
  33.  * Notes:
  34.  * ~~~~~~
  35.  * This code #includes a header clipper.h, which is simply the virtual
  36.  * concatenation of the files nandef.h and extend.h distributed with Clipper.
  37.  *
  38.  * In case of difficulty using this together with other libraries (such as
  39.  * with super.lib), use the linker option /NODEFAULTLIBRARYSEARCH (/NOD)
  40.  * and specify the C library llibca.lib (*not* llibce.lib) explicitly.
  41.  *
  42.  * To compile this, use MS C switches '-AL -Zl -Oalt -FPa -Gs'.  For example,
  43.  * if your default rule for C in make.ini uses $(MODEL),
  44.  *
  45.  *    make regxsrch.obj MODEL=L CFLAGS='-Zl -Oalt -FPa -Gs'
  46.  *
  47.  * Assuming you are using GNU make and have the following default rule in
  48.  * make.ini:
  49.  *
  50.  *    # To produce a `.exe' file from a `.prg' file (the root of the code tree)
  51.  *    # using Clipper.
  52.  *    %.exe : %.prg
  53.  *        $(CLPC) $< $(CLPFLAGS)
  54.  *        $(LD) $(CLPLDFLAGS) $* $(XOBJS),$@,nul, $(CLPLIBS) $(XLIBS) ;
  55.  *
  56.  * you can compile a Clipper program tst.prg that uses this as follows:
  57.  *
  58.  *    make tst.exe XOBJS=regxsrch.obj CLPLDFLAGS='/se:512 /noe /nod' XLIBS='gnulib_l llibca'
  59.  *
  60.  *
  61.  * Returns:
  62.  * ~~~~~~~~
  63.  *        -4 on parameter error,
  64.  *        -3 on memory allocation (_exmgrab) error,
  65.  *        -2 on regex error (regex compilation failed),
  66.  *        -1 on no match,
  67.  *        or the index (base 0) of the match.
  68.  *
  69.  *
  70.  * History:
  71.  * ~~~~~~~~
  72.  *   18 Jan 92    RjR    - Initial version.
  73.  *   19 Jan 92    RjR    - Bug fixes and cleanup of the Clipper interface.
  74.  *   20 Jan 92    RjR    - Do the _exmgrab() only once, for speed and to avoid
  75.  *              possible memory fragmentation.  This gets us a 10%
  76.  *              speed gain.
  77.  *            - Buffer the regex from the last call, and do not
  78.  *              recompile it if the current regex is the same.
  79.  *              This gets us a further 35% speed gain.
  80.  *            - Arrange things so that there is only one exit point.
  81.  *            - Clean up in-code documentation.
  82.  *            - Added debugging code.  Define DEBUG to use it.
  83.  *  21 Jan 92    RjR    - Cleanup and inspection.
  84.  *
  85.  *
  86.  * Author:
  87.  * ~~~~~~~
  88.  * Richard Reiner <rreiner@nexus.yorku.ca>
  89.  *
  90.  *
  91.  * Distribution:
  92.  * ~~~~~~~~~~~~~
  93.  * Copyright (C) 1992, Richard Reiner
  94.  *
  95.  * regxsrch.c comes with ABSOLUTELY NO WARRANTY.  This is free software,
  96.  * and you are welcome to distribute it under the terms of the GNU General
  97.  * Public License, which covers both the warranty information and the
  98.  * terms for redistribution.
  99.  *
  100.  * See the file COPYING in the GNULIB distribution for details.
  101.  *
  102.  */
  103.  
  104.  
  105. #ifdef DEBUG
  106. #   define DEBUG_MSG(m) printf(m)
  107. #else
  108. #   define DEBUG_MSG(m)
  109. #endif
  110.  
  111. #include <regex.h>
  112. #include <math.h>
  113. #include <clipper.h>
  114. #include <stdlib.h>
  115. #include <string.h>
  116.  
  117. #ifdef DEBUG
  118. #   include <stdio.h>
  119. #endif
  120.  
  121. #define PATBUFSIZ    2048
  122. #define FMAPSIZ        256
  123. #define LASTREGEXBUFSIZ    256
  124.  
  125. CLIPPER regex_srch (void) {
  126.     static struct re_pattern_buffer    *rbuf;
  127.     static char                *fmap, *lastregex;
  128.     static int                callcount = 0, retval = -2;
  129.     register int            parlen;
  130.  
  131.     /* if the Clipper parameters are of the right number and type */
  132.     if (PCOUNT == 2 && ISCHAR(1) && ISCHAR(2)) {
  133.     /*
  134.      * Allocate memory the first time we are called.  We do not
  135.      * allocate and free (_exmgrab() and _exmback()) each time we are
  136.      * called, since the time required for allocation and freeing is
  137.      * quite high relative to the time required for the actual regex
  138.      * match.  Instead we alloc once, and never free until Clipper
  139.      * does it for us at the Clipper program's termination.
  140.      */
  141.     if (callcount == 0) {
  142.         callcount++;
  143.         /* allocate memory from Clipper */
  144.         fmap = _exmgrab(FMAPSIZ);
  145.         rbuf = (struct re_pattern_buffer *) _exmgrab(sizeof (struct re_pattern_buffer));
  146.         rbuf->buffer = _exmgrab(PATBUFSIZ);
  147.         lastregex =  _exmgrab(LASTREGEXBUFSIZ);
  148.  
  149.             /* ensure lastregex is null terminated */
  150.         lastregex[LASTREGEXBUFSIZ - 1] = '\0';
  151.     }
  152.  
  153.     /* if one of the _exmgrab()s failed */
  154.     if (fmap==NULL || rbuf==NULL || rbuf->buffer==NULL || lastregex==NULL) {
  155.         /* store allocation error indication for Clipper */
  156.         retval = -3;
  157.     } else {    /* _exmgrab()s were OK */
  158.         /* initialize rbuf fields */
  159.         rbuf->allocated = PATBUFSIZ;
  160.         rbuf->translate = 0;
  161.  
  162.         /* store length of target string for later repeated use */
  163.         parlen = _parclen(1, 1);
  164.  
  165.         /* if this regex is not the same as the last one */
  166.         if (strncmp(lastregex, _parc(2,1), LASTREGEXBUFSIZ - 1) != 0) {
  167. #ifdef DEBUG
  168.         DEBUG_MSG("Regex not the same as previous.\n");
  169. #endif
  170.         /* store the regex for next time */
  171.         strncpy(lastregex, _parc(2,1), LASTREGEXBUFSIZ - 1);
  172.         /* compile the regex */
  173.         if (re_compile_pattern(_parc(2,1), _parclen(2,1), rbuf) != 0) {
  174.             /* store compilation error indication for Clipper */
  175.             retval = -2;
  176.         } else { /* the compilation was successful, so we search */
  177.             rbuf->fastmap = fmap;
  178.             retval = re_search(rbuf, _parc(1,1), parlen, 0, parlen-1, 0);
  179.         }
  180.         } else {    /* regex is the same as the last one, so no need to recompile */
  181.         DEBUG_MSG("Regex same as previous.\n");
  182.         /* Search only if the last search, which was using this
  183.             same regex, did not produce an error.  Otherwise, don't
  184.             change anything */
  185.         if (retval >= -1) {
  186.             retval = re_search(rbuf, _parc(1,1), parlen, 0, parlen-1, 0);
  187.         } else {
  188.             DEBUG_MSG("Last attempt produced error; not searching.\n");
  189.         }
  190.         }
  191.     }
  192.     } else { /* Clipper parameters were not OK */
  193.     /* store parameter error indication for Clipper */
  194.     retval = -4;
  195.     }
  196. #ifdef DEBUG
  197.     printf("retval == %d.\n",retval);
  198. #endif
  199.     _retni(retval);
  200.     return;
  201. }
  202.